home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-08-02 | 49.8 KB | 1,074 lines |
-
- DSO(5) Silicon Graphics DSO(5)
-
- NAME
- DSO - Dynamic Shared Object
-
- TOPIC
- This man page is intended to be both a quick reference and a source of
- detailed information on Dynamic Shared Objects. It is divided into 4
- sections:
-
- General Information and Overview
-
- Linking/Building Suggestions
-
- Performance Considerations
-
- Frequently Asked Questions and Detailed Discussions
-
- GENERAL INFORMATION AND OVERVIEW
- Format
- A DSO, or Dynamic Shared Object, is an ELF format object file, very
- similar in structure to an executable program but with no "main". It has
- a shared component, consisting of shared text and read-only data; a
- private component, consisting of data and the GOT (Global Offset Table);
- several sections that hold information necessary to load and link the
- object; and a liblist, the list of other shared objects referenced by
- this object. Most of the libraries supplied by SGI are available as
- dynamic shared objects.
-
- PIC -- Position Independent Code
- A DSO is relocatable at runtime; it can be loaded at any virtual address.
- A consequence of this is that all references to external symbols must be
- resolved at runtime. References from the private region (.e.g. from
- private data) are resolved once at load-time; references from the shared
- region (e.g. from shared text) must go through an indirection table (GOT)
- and hence have a small performance penalty associated with them.
-
- Code compiled for use in a shared object is referred to as PIC whereas
- non-PIC is usually referred to as non-shared. Non-shared code and PIC can
- not be mixed in the same object.
-
- What Happens at Runtime?
- Exec loads the main program and then loads rld(1), the runtime linking
- loader, which finishes the exec operation. Starting with main's liblist,
- rld loads each shared object on the list that is not marked as delay
- load, reads that object's liblist, and repeats the operation until all
- shared objects have been loaded. Next, rld allocates common and fixes up
- symbolic references in each loaded object. (This is necessary because we
- don't know until runtime where the object will be loaded.) Next, each
- object's init code is executed. Finally, control is transferred to
- "__start".
-
- Page 1 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- Be sure to read about quickstart, delayed loads, sgidladd(3), and
- dlopen(3) as each can affect this general process.
-
- LINKING / BUILDING DYNAMIC SHARED OBJECTS
- Example
- Suppose your library is in an archive libfoo.a of object files all of
- which have been compiled -shared; and it references symbols found in
- libc.so, libgl.so, libX11.so and libnetls.so though most programs will
- never use the path that requires libnetls.so. SGI recommends building
- your DSO, libfoo.so, in the following way:
-
- ld \
- -elf \
- -shared \
- -no_unresolved \
- -rodata_shared \
- -o libfoo.so \
- -all libfoo.a \
- -lX11 \
- -delay_load -lnetls \
- -lc \
- -lgl
-
- This builds a DSO called libfoo.so that will request rld to load libc.so,
- libX11.so, and libgl.so whenever libfoo.so is loaded and will load
- libnetls.so if it is ever referenced.
-
- Controlling The Symbols Exported By A Dynamic Shared Object
- In building a dynamic shared object it is necessary that the control is
- maintained over which symbols are exported by that object. One of the
- benefits of using dynamic shared objects is the ability to release new
- versions of that object and still have objects that were linked against
- the old version, work with the new version. This will be impossible to
- guarantee, if the set of symbols exported by an object can not easily be
- understood by object's creator. ld provides several options that will
- aid the developer in controlling which symbols are exported by a dynamic
- shared object.
-
- By default ld will not export symbols that are supplied by a linked-in
- archive or dynamic shared object. In either of these cases the developer
- is probably only a consumer of the linked-in object, not an exporter. In
- a subsequent release, the developer may not require the linked-in object
- and if the symbols provided by the linked-in object had been exported by
- the developer's object, the new object would not longer be upwardly
- compatible with the original version. This behavior can be overridden
- using the -exports option. This behavior, with respect to archives, is
- also overriden when building a dynamic shared object from an archive
- using the -all option.
-
- The developer can provide even greater control over the list of symbols
- that are exported using options -exported_symbol, -exports_file, -
- hidden_symbol, or -hides_file. The first two options lets the developer
-
- Page 2 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- specifically list the symbols that are to be exported by the dynamic
- shared object. The -exported_symbol option is followed by a comma
- separated list of names. The -exports_file option gives a filename that
- contains a space separated (including newlines) list of names. If any
- symbols are specifically exported, then only those symbols will be
- exported. All other symbols are automatically hidden. The last two
- options lets the developer specify a list of symbols that are to be not
- exported by the dynamic shared object.
-
- There are two consequences of hiding symbols. First, those symbols will
- not provide resolution to any undefines in an object that links in the
- dynamic shared object. Second , any references to that symbol within the
- dynamic shared object will be resolved internally to the hidden symbol.
-
- Rules Of Thumb
- Use -no_resolved to find unresolved symbols. While it is not always
- possible to supply on the link line all the shared objects that will be
- referenced by libfoo.so, in general, libraries should be self-contained.
- This is especially true for subsequent releases of a dynamic shared
- object. If a dynamic shared object has any unresolved references, they
- must be resolved by some other loaded object. Having unresolved symbols
- invites disaster since there is no guarantee that the symbols will be
- resolved and thus the application will not run.
-
- Link against the minimum set of .so's needed. Loading a shared object
- does carry a cost. Linking against unneeded dynamic shared objects will
- cause them to be loaded even if they are never referenced. ld will
- provide a warning when you have linked against a dynamic shared object
- that resolves no symbols.
-
- When building a c++ dynamic shared object, specify -exports for any
- dynamic shared object that provides the definitions of classes that
- classes in the object being created derive from. Specifying -exports in
- this case will make sure consumers of the object being created will be
- able to create subclasses of classes provided by that object, without
- having to know the complete set of dynamic shared objects that will need
- to be loaded. Using the -exports flag in this case may bring in unwanted
- symbols. In that case using the -exported_symbol, -exports_file, -
- hidden_symbol, or -hides_file. options may be necessary.
-
- Use -rodata_shared to move all read-only data into the shared segment.
- Unfortunately, there are many programs that write to supposedly read-only
- data; for this reason, this option is off by default. The compiler
- option, -use_readonly_const, is on by default.
-
- If you reference the gl, have it last in the link line. Often libgl.so
- cannot be quickstarted (see below); putting it last allows all the
- "upstream" objects to still be quickstarted. You can also choose to
- delay load libgl.so. This will still allow your application to
- quickstart.
-
- Page 3 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- Anytime a "downstream" shared object (a referenced object) changes, you
- should relink in order to quickstart.
-
- Try to minimize inter-DSO data references.
-
- Try to minimize the use of global data. In DSO's, it is generally more
- efficient to malloc space when needed rather than use a large static data
- structure.
-
- Try to pack data together that is likely to be unmodified. This allows
- the kernel to make more of the data pages shared, copy-on-write.
-
- Use the -delay_load option on any shared object on the link line that is
- not often used. This adds a small performance penalty for references to
- it, but can save time and memory for those programs that don't use it.
-
- Do not call sproc from any code that may be executed at init time.
-
- PERFORMANCE CONSIDERATIONS
- Quickstart
- When building a shared object or an executable, ld assigns addresses to
- the object and attempts to resolve all references. At runtime, if rld
- verifies that the same set of objects are loaded at the original
- addresses, then rld can skip all the runtime relocation work and let the
- program run. This saves time by skipping doing the relocations and saves
- memory since rld does not have to read in the sections that hold the
- relocation information.
-
- At static link time, ld will resolve any unresolved function calls to a
- stub routine which references an rld function called lazy_text_resolve().
- When invoked at runtime, it performs the relocation needed for all future
- calls to the original function. In this way, more programs can quick
- start even if some of the function references are not resolved at static
- link time.
-
- Quickstart will fail whenever the dynamic shared objects on a system do
- not match the objects used when linking and application or the shared
- objects that it depends on. This will occur whenever a new version of a
- dynamic shared object is released. When quickstart fails rld has to do a
- significant amount of work. The rqs(1) command can be used to
- recalculate the quickstart information associated with an application or
- a dynamic shared object. rqs must be called in proper order so that
- dynamic shared objects on an objects liblist are requickstarted before
- the object ir requickstarted. rqs will rewrite the object it is
- requickstarting back in place. It is possible to mark an object as non-
- requickstartable by using the -no_rqs flag to ld.
-
- Avoiding Gratuitous Shared Object Loads
- Since for each shared object that is loaded, rld does a considerable
- amount of work and can use up large amounts of real memory, it is
- advantageous to not link against shared objects that are not needed.
-
- Page 4 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- dlopen(3), sgidladd(3), and delayed loads
- The overhead associated with objects that are referenced but seldom
- actually used can be mitigated by using dlopen(3), sgidladd(3), or
- delayed loads. The use of any of these, delays the loading of a shared
- object (and the objects on it's liblist) until it is actually referenced.
- The most convenient is the -delay_load option to ld. All three require
- that there be no references from any other objects' data section to the
- delay loaded shared object.
-
- FREQUENTLY ASKED QUESTIONS
- List of Questions:
-
- 1) What is DSO?
- 2) How do dynamic shared objects compare with shared libraries?
- 3) How do I maintain binary compatibility between versions of dso's?"
- 4) Under which versions of the OS can I use DSO?
- 5) What object-file format does DSO use?
- 6) How do I install the tools so I can use DSO on my system?
- 7) How do I build an executable that uses a shared object?
- 8) How do I build an executable that doesn't use shared linking?"
- 9) How do I tell if an executable will use dynamic linking?
- 10) How do I build a shared object?
- 11) Where does the system look for shared objects at runtime?
- 12) What is Quickstart?
- 13) What is the so_locations file?
- 14) What directives can be put in a so_locations file?
- 15) What is /usr/lib/so_locations?
- 16) If I don't have a valid so_locations, can I generate one from all
- the .so's in, say, /usr/lib?"
- 17) How expensive is it (at runtime) to NOT use the -update_registry
- option?"
- 18) How and when will Quickstart be used?
- 19) What about run-time loading under user control?
- 20) What benefits will I get from DSO?
- 21) What costs are associated with DSO?
- 22) What is the -KPIC option?
- 23) Must main programs which want to use DSO's use -KPIC for compilation?"
- 24) How do I change my assembly language sources to use -KPIC?
- 25) Can I mix IRIX 4 static shared libraries with DSO's?
- 26) What options do I have when building a shared object?
- 27) What pitfalls should I know about which are associated with DSO?"
-
- Page 5 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- 28) What should I do about a GOT overflow?
- 29) How are multiple versions of DSO's supported?
- 30) Where can I find more documentation on DSO?
- 1) What is DSO?
- DSO stands for Dynamic Shared Objects. DSO provides a capability similar
- to static shared libraries under Cypress and earlier versions of the
- IRIX, e.g., it gives applications the ability to share the text of
- heavily used libraries, which need not be included in the executable
- file. However DSO has two important distinctions from static shared
- objects.
-
- 2) How do dynamic shared objects compare with shared libraries?
- First, a dynamic shared object contains only position-independent code,
- so that it may be mapped into the virtual address space of different
- processes at different addresses and still be shared. Second, dynamic
- shared objects, and indeed the executable itself are mapped in by a
- runtime loader, rld, which resides in memory in the same address space as
- the executable. This gives the system the ability to change the binding
- of symbols during executions, at the request of the executing program.
- This capability should prove useful across a large segment of
- applications.
-
- 3) How do I maintain binary compatibility between versions of dso's?
- As long as the shared objects maintain the same exported symbols, or
- perhaps add new symbols without removing any or changing semantics, and
- don't change exported structures, they will be binary compatible.
- Ordering of symbols, routines, are irrelevant, as global data, etc. We
- are working on a system called Delta-C++ which should allow you to add to
- exported classes without recompiling.
-
- 4) Under which versions of the OS can I use DSO?
- DSO is available under IRIX versions 5.0 and later. Programs built with
- DSO will not work on earlier version of IRIX.
-
- 5) Which object-file format does DSO use?
- DSO uses the ELF object file format, as defined in the SVR4 ABI. ELF
- objects cannot be run under IRIX 4.0.5 or earlier.
-
- 6) How do I install the tools so I can use DSO on my system?
- IRIX 5.0 and later releases all support/use DSO's. In order to compile
- and build shared objects you will need to have the Developer's option
- installed.
-
- 7) How do I build an executable that uses a shared object?
- cc myfile.c -lmine
-
- This will link you with libmine.so and also with libc.so.1, if either are
- available. If no libmine.so is available, but there is a libmine.a, the
- libmine.a will be used along with libc.so.1, and you will still get
- dynamic linking. If you wish to be explicit, add the -call_shared flag
- to the cc line:
-
- Page 6 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- cc -call_shared myfile.c -lmine
-
- 8) How do I build an executable that doesn't use shared linking?
- Use the -non_shared flag:
-
- cc -non_shared myfile.c -lmine
-
- 9) How do I tell if an executable will use dynamic linking?
- elfdump -o shows you the ELF program header. This contains all the
- information necessary for exec and rld to run the program/shared object.
- Only a.outs which use dynamic linking will have a PHDR, INTERP, or
- DYNAMIC entry.
-
- Here's an example, and a more detailed description of this stuff.
-
- % elfdump -o /bin/cat
-
- ***PROGRAM HEADER***
- Type Offset Vaddr Paddr Filesz Memsz Align RWX
- PHDR 0x00000034 0x00400034 0x00400034 0x000000c0 0x00000000 0x00000004 r--
- INTERP 0x00000100 0x00400100 0x00400100 0x00000009 0x00000009 0x00000004 r--
- REGINFO 0x00000110 0x00400110 0x00400110 0x00000018 0x00000018 0x00000004 r--
- DYNAMIC 0x00000150 0x00400150 0x00400150 0x00000a70 0x00000a70 0x00000010 r--
- LOAD 0x00000000 0x00400000 0x00400000 0x00003000 0x00003000 0x00001000 r-x
- LOAD 0x00003000 0x10000000 0x10000000 0x00001000 0x00001290 0x00010000 rwx
-
- Each line is an entry in the program header, and refers to a "segment" of
- the file.
-
- PHDR points to the program header itself within the file. Only
- executables which use dynamic linking will have this field.
-
- INTERP
- points to a place in the file where the name of the interpreter
- required for this program is to be found. For any ABI-conforming
- object, this name will be "/usr/lib/libc.so.1".
-
- REGINFO
- points to a place in the file where information about register setup
- can be found. Currently this mostly consists of the correct gp
- value for this object.
-
- DYNAMIC
- points to the information in the file which is needed by rld to
- execute it correctly. This information includes the liblist, a
- symbol table, and other information.
-
- LOAD points to segments that are to be mapped into the memory image.
-
- Page 7 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- The columns give various information about each segment.
-
- Offset
- is the offset in the file to the beginning of the segment.
-
- Vaddr
- is the virtual address of the beginning of the segment in the memory
- image of the file, ASSUMING that it was mapped as described in the
- LOAD entries
-
- Paddr
- is the same as Vaddr in our implementation.
-
- Filesz
- is the size of the segment in the file.
-
- Memsz
- is the size of the segment in the memory image. When this is larger
- it is assumed to be zero-filled.
-
- Align
- is the alignment required by this section. If an segment is to be
- mapped somewhere into memory other than at Vaddr, the new address
- must be congruent to Vaddr modulo the alignment. In the example
- above, the first segment must always be loaded at a page boundary,
- and the second must always be loaded at a 64K boundary.
-
- RWX specifies the protections r(ead), w(rite), or x(ecute) for the
- segment.
-
- Programs which are linked -non_shared do not have a PHDR, INTERP, or
- DYNAMIC section. Thus elfdump -o is a convenient method to determine if
- a program is linked -non_shared or not.
-
- 10) How do I build a shared object?
- To begin with, build a .o or .a which contains all the routines you want
- to have in your .so (shared object). This can be done with cc -c and ar.
- Then invoke ld with the -shared flag. Normally the extension .so is used
- to designate shared objects.
-
- Here is an example:
-
- cc -c myobj.c
- ld -shared myobj.o -o myobj.so
-
- -or-
-
- <build libmine.a the usual way.>
- ld -shared -all libmine.a -o libmine.so
-
- Page 8 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- The -all flag in the second example tells ld to include all the routines
- in the library. This is necessary since there are no undefined
- references (in a main, say) which is the usual way that ld knows to
- include files from an archive.
-
- 11) Where does the system look for shared objects at runtime?
- The search path for shared objects is acquired in the following order:
-
- 1) the path of the shared object if given in the liblist,
-
- 2) in any directories specified via the
- -rpath flag when the executable was built
-
- 3) in any directory specified by the LD_LIBRARY_PATH environment
- variable, if it is defined
-
- 4) in the directories in the default path
- (/usr/lib:/lib:/lib/cc:/usr/lib/cc)
-
- If the _RLD_ROOT environment variable is defined, then its value is
- appended to the front of any path specified by -rpath and the default
- path. _RLD_ROOT itself is also a colon(:) separated list.
-
- See the rld(1) manpage for details.
-
- 12) What is Quickstart?
- Quickstart is an optimization. Using the so_locations file, each shared
- object is pre-relocated by ld, as if it had been loaded at the address in
- the so_locations file. That way, if nothing unusual happens when we
- start up the application, all the shared objects will map at their
- Quickstart addresses, and rld will not need to do a relocation pass over
- them.
-
- If for some reason more than one shared object wishes to map the same
- address, rld will move one of them to an unused address and perform a
- relocation pass to fix up the address references.
-
- If one or more of the shared objects linked against at static link time
- has changed by the time the program executes, rld will need to do extra
- work to ensure that symbols have been resolved to their proper value.
-
- 13) What is the so_locations file?
- In the directory in which you build a shared object, after you've
- actually built one, you will notice a file named so_locations.
-
- It is a registry of shared objects. It maintains the default or
- Quickstart addresses of a group of shared objects which are to cooperate
- by not having their default location overlap with one another. It is
- generated and updated by ld each time it builds a shared object.
-
- Page 9 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- 14) What directives can be put in an so_locations file?
- Comment line
- so_name [ :st = { .text | .data | $range } base_addr,padded_size : ] *
-
- where
- so_name full path name (or trailing component) of a
- shared object
- st string identifying start of the segment description
- .text | .data segment types: text or data
- $range limit the range of address that can be used
- base_addr address where the segment starts
- padded_size padded size of the segment
-
- The following directives control the placement of new shared objects:
-
- $text_align_size=<align> padding=<pad-size>
- $data_align_size=<align> padding=<pad-size>
- These two directives specify the alignment and padding
- requirements for text and data segments respectively.
- The size value in so location is calculated based on:
- (section size + padding) aligned to the section align size
- The align values for text and data as well as the padding
- values must be aligned to a bucket size. If not, ld will
- generate a warning message and align these values to bucket
- size.
-
- $start_address=<addr>
- Specifies where to start looking for addresses to put shared
- objects.
-
- $data_after_text=[ 1 | 0 ]
- Instructs the linker to place data immediately after the text
- at specified text and data alignment requirements.
- We set the data_after_text to 0 if the argument of this directive
- is missing.
-
- Also, when building a dso with the -check_registry or -update_registry
- flag, and if there is already an entry corresponding to this dso in the
- so_location file, the linker will try to assign the same addresses for
- text and data. However, if the size of the dso changes and does not fit
- in the specified location any more, the linker will search for another
- spot that fits. If the optional $range comment is given, the linker will
- only place the dso in the specified range of addresses. If there is not
- enough room, an error will be given.
-
- 15) What is /usr/lib/so_locations?
- This file represents the default layout for the system shared objects.
- Developers who build shared objects may find it interesting to consult
- this file, in order to avoid collisions between their shared objects and
- system shared objects. This file is absolutely irrelevant to users who
- merely run programs which use shared objects.
-
- Page 10 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- There are two options which are relevant, -update_registry, and <file>
- looks at <file> and builds the current .so at a location which doesn't
- conflict with anything in the file (unless the current one is listed. -
- check_registry does not write to <file>. -update_registry <file> will
- consult <file> as with -check_registry, but will attempt to write an
- entry for the .so being built into <file>. If <file> is not writable, -
- update_registry turns into If <file> is not readable -check_registry and
- -update_registry are ignored.
-
- 16) If I don't have a valid so_locations file, can I generate one from all
- the .so's in, say, /usr/lib?
- There is no convenient method to do so. There is no guarantee that all
- the .so's in /usr/lib have been coordinated so that a consistent
- so_locations file can be made from them. So it is better to get the one
- that a particular release was made with.
-
- 17) How expensive is it (at runtime) NOT to use -update_registry option?
- The costs are all startup costs. It is very difficult to say how much a
- particular executable will suffer since it depends on which shared
- objects the program uses and whether they have been Quickstarted for the
- same address. When there is a conflict between two objects, one will be
- moved, which means that all addresses referring to names in that object
- need to be relocated.
-
- 18) How and when will Quickstart be used?
- Normally, the linker will use Quickstart unless there are unresolved
- symbols at static link time.
-
- In every executable and every shared object is a list of objects which
- were looked at at static link time -- when the object was made. This
- list also contains timestamps and checksums for each of the objects.
- Various levels of extra work are required if the timestamp or checksum
- has changed in the library at run-time.
-
- 19) What about run-time loading under user control?
- We support an interface known as libdl, which allows users to dynamically
- load their own shared objects as needed. The calls are
-
- dlopen() -- open a new shared object and get a "handle" to it.
-
- dlsym() -- find the value of a name defined in an object.
-
- dlclose()-- close a shared object.
-
- dlerror()-- report errors.
-
- sgidladd() -- functions much like dlopen however it exposes
- all symbols to the rest of the program.
-
- Consult the individual manpages for details.
-
- Page 11 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- 20) What benefits will I get from DSO?
- Executables linked with shared objects will be smaller since the shared
- objects are not part of the executable file image.
-
- Executables which use a shared object need not be relinked if a shared
- object is changed -- once the updated shared object is installed, the
- executable will pick it up automatically.
-
- Shared libraries are much easier to build, use, and debug than static
- shared libraries.
-
- DSO allows application designers to make more machine-independent
- software. System-dependent routines can be given a uniform interface and
- a shared object which implements that interface can be built for each
- different platform. Then an actual application can be shipped as-is
- ("shrink-wrapped" software) to various platforms and run on them all.
-
- DSO gives applications the ability to change the binding of symbols at
- run time, under user control.
-
- 21) What costs are associated with DSO?
- A shared object incurs two costs, both against performance.
-
- At startup, there will be a startup cost while rld maps in the various
- objects, performs symbol resolution, etc. We believe this cost is small
- compared to the time it takes to contact the X server, for example.
- Quickstart will reduce this time for smaller applications.
-
- A shared object's text must be PIC (position independent code).
- PICification is accomplished by the code generator (ugen) and assembler
- (as), when the -KPIC flag is specified. This is the default However, PIC
- code is necessarily slower. Experiments have indicated that this speed
- reduction is usually less than 5 percent, but can be as much as 15
- percent. depending on the application. PIC code seems to be worst on
- very small leaf routines which access global data.
-
- 22) What is the -KPIC option?
- This flags tells the code generator and assembler to generate PIC
- directly. The result is an object file that can be put into a DSO
- without further modification
-
- cc -KPIC -c foo.c
-
- will give you a PIC object foo.o. Other drivers (cc, pc, f77, and as)
- also accept the -KPIC option. This is the default.
-
- Routines written in assembly languages need to be modified before -KPIC
- can be used. See the question below.
-
- PIC objects generated by using -KPIC must be compiled -G 0.
-
- Page 12 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- 23) Must main programs which want to use DSO's use -KPIC for compilation?
- Yes. DSO's use -KPIC so that position-independent code will be
- generated. Main programs are not generally position-independent, but
- must still use the DSO calling convention when calling a routine which is
- defined in a DSO. In particular, this means that a main program must have
- a GOT, and the code which is generated must use it. Therefore, modules
- which will become part of main programs must be compiled -KPIC as well as
- modules which become part of DSO's.
-
- 24) How do I change my assembly language sources to use -KPIC?
- Several new assembler directives are added to support generation of PIC.
- You should also get yourself familiar with the MIPS ABI Supplement and
- the PIC coding model it describes. In addition, files which are to be
- assembled with -KPIC must also be -G 0. This is normally turned on by
- the driver by default.
-
- Note that with the exception of (a) and (d), all other directives
- described below will be ignored when -KPIC is not explicitly specified.
- Also, item (d), ".gpword", will be turned into ".word". The result will
- be a NON-PIC version of the same routine.
-
- a) .option pic2
-
- This directive forces the assembler to mark the output object file "PIC"
- and activates the following directives. It overrides the command line
- argument. Normally, you don't need to specify this directive. Instead,
- you should use the -KPIC or -non_shared flags to toggle between
- generating PIC or non-PIC.
-
- Note that even though -KPIC will be made the default for the high-
- language driver (cc/pc/f77) in future releases, it will *NOT* be the
- default for assembly sources. You will always have to explicitly specify
- -KPIC for compiling .s files.
-
- b) .cpload reg
-
- This directive expands into three instructions that sets the gp register
- to the context pointer value for the current function. The three
- instructions are:
- lui gp,_gp_disp
- addui gp,gp,_gp_disp
- addu gp,gp,reg
-
- _gp_disp is a reserved symbol defined by the linker to be the distance
- between the lui instruction and the context pointer. This directive is
- required at the beginning of each subroutine that uses the gp register.
-
- You must add this directive at the beginning of every procedure, with the
- exception of leaf-procedures that do not access any global variables, and
- procedures that are static (i.e., not marked .globl or .extern).
-
- Page 13 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- c) .cprestore offset
-
- This directive causes the assembler to issue
- sw gp,offset(sp)
- at the point where it appears. Additionally, it causes the assembler to
- emit
- lw gp,offset(sp)
- after every jump-and-link (jal) or branch-and-link (bal) operation,
- thereby restoring the gp register after function calls. The programmer
- is responsible for allocating the stack space for the gp. This space
- should be in the saved register area of the stack frame to remain
- consistent with MIPS' calling and debugger conventions.
-
- d) .gpword local-sym
-
- This directive is similar to .word except that the relocation entry for
- local-sym has the R_MIPS_GPREL32 type. After linkage, this results in a
- 32-bit value that is the distance between local-sym and the context
- pointer (i.e. the gp). local-sym must be local. It is currently used
- for PIC switch tables.
-
- e) .cpadd reg
-
- This adds the value of the context pointer (gp) to reg.
-
- EXAMPLES:
- This is a simplified version of the "hello world" program:
- --------------------------------------------------------------
- .option pic2
- .data
- .align 2
- $$5:
- .ascii "hello world\X0A\X00"
- .text
- .align 2
- main:
- .set noreorder
- .cpload $25
- .set reorder
- subu $sp, 40
- sw $31, 36($sp)
- .cprestore 32
- la $4, $$5
- jal printf
- move $2, $0
- lw $31, 36($sp)
- addu $sp, 40
- j $31
- ----------------------------------------------------------------
- The actual instructions generated by the assembler will be:
-
- lui gp,0 #
-
- Page 14 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- addiu gp,gp,0 # generated by .cpload
- addu gp,gp,t9 #
- lw a0,0(gp) # gp-relative addressing used
- lw t9,0(gp) # t9 is used for func. call
- addiu sp,sp,-40
- sw ra,36(sp)
- sw gp,32(sp) # from .cprestore
- jalr ra,t9 # jal is changed to jalr
- addiu a0,a0,0
- lw ra,36(sp)
- lw gp,32(sp) # activated by .cprestore
- move v0,zero
- jr ra
- addiu sp,sp,40
- nop
- ----------------------------------------------------------------
-
- NOTE:
-
- The MIPS's ABI required register t9 ($25) be used for indirect function
- call, so .cpload should always use $25. No reorder mode should also be
- used. Also, programmers should make sure that t9 is dead before any
- function call.
-
- If your program uses an indirect jump (jalr), you must also use t9 as the
- jump register.
-
- If you have an unconditional jump to an external label:
- j _cerror
- you have to rewrite it into indirect jump via t9, i.e.:
- la t9,_cerror
- j t9
-
- If you use branch-and-link (bal) instruction, and if the target procedure
- begins with a .cpload, you have to specify an alternate entry point:
-
- foo: .set noreorder # callee
- .cpload $25
- .set reorder
- $$1: ... # alternative entry point
- ...
- j $31 # foo returns
-
- bar: ... # caller
- ...
- bal $$1 # by-pass the .cpload
- ...
-
- This is very important because .cpload assumes register $25 contains the
- address of foo, but in this case $25 is not set up. Note that since both
- foo and bar reside in the same file, they must have the same value for
- $gp. So the .cpload instructions can be and must be bypassed. However,
-
- Page 15 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- since foo can still be called from outside, the .cpload is still
- required.
-
- Alternatively, if you don't want to have an alternate entry point, you
- can set up register $25 before the bal:
- la t9,foo
- bal foo
-
- but this will be less efficient.
-
- position-independent jump table (or any table of text addresses).
- Entries of the address table created by .gpword are converted into
- displacement from the context pointer. To get the correct text address,
- .cpadd should be used to add the value of gp back to them. Since the gp
- is updated by the run-time linker, the correct text address can be
- reconstructed regardless of the location of the dso.
-
- 25) Can I mix IRIX 4 static shared libraries with DSO's?
- We do not anticipate ever allowing an a.out to use both static shared
- libraries and dso.
-
- 26) What options do I have when building a shared object?
- If you specify the flag -B dynamic while linking a shared object, symbols
- in the shared object will be resolved differently than the default
- linkage convention. In particular, the runtime linker will always try to
- resolve any symbols referenced in that object to symbols defined in that
- object first, instead of looking for definitions in objects in the order
- specified on the link line.
-
- The effect of this is to make all symbols defined and used in such
- objects non-preemptable. Ordinarily a such symbol definitions could be
- preempted by a definition in an earlier shared object, but when -B
- symbolic is specified, this is not the case.
-
- 27) What pitfalls are associated with DSO?
- Behind most of the surprises that users will get is the fact that linking
- semantics are fundamentally different, but only in a subtle way. Let us
- suppose that your program links with three libraries, libA, libB and
- libC, in that order. Further suppose that both libA and libC define some
- symbol x, but don't use it. Furthermore, let us suppose that libB
- contains a reference to x. Archive linking (the old way) will resolve
- B's reference to x to the definition in C, whereas shared object linking
- will resolve B's reference to x to the definition in A.
-
- Why the difference? With archive linking, when libA is examined, there
- is no outstanding reference to x, hence the definition of x is not
- extracted from the archive. Later when libC is examined, there is a
- reference to x, so it is loaded.
-
- With shared objects, all the constituent object files have been joined
- into one object, so all symbol definitions are always present. The
- resolution rule is simple, take the definition in the object listed
-
- Page 16 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- first. Thus the definition in libA is used.
-
- Another sort of surprise is the "runtime dangling reference". It is
- altogether possible to build and link an application with no errors or
- even warnings, only to get a message from rld stating that your program
- has unresolvable symbols.
-
- What's going on? Well, if you build a shared object as part of your
- program, the linker will not normally complain about undefined symbols
- during a link of a shared object. This is because undefined symbols are
- expected during such a build and are perfectly acceptable. But if the
- main program does not use a symbol, it does not get flagged as undefined
- during static linking. Thus the runtime "surprise". You can use the -
- no_unresolved flag to the linker to avoid such surprises.
-
- Now we get to a nasty pitfall which can be avoided by some cleverness in
- building a shared object. If a particular object in an archive has an
- external reference to a data symbol (which it expects to be defined in
- main, libl.a, for example) the linker would not try to resolve that
- external unless the object file in question was actually referenced by
- the main program. Now if that archive is turned into a shared object
- naively, the external data reference must be resolved whenever ANY
- function in the shared object is used, even if no function in the object
- file in question is ever called and no use is made of the external data
- symbol in question.
-
- This can lead to a scenario where a user has a link that worked with the
- archives, but builds a program which gets nuked by the runtime linker
- under the new scheme of things. I believe that it is a very bad idea for
- us to convert libraries. such as libl.a, which contain external data
- symbols, to shared objects naively.
-
- One thing that can be done is to split the archive into several shared
- objects which are placed on the liblist of a "master" shared object.
- Since rld will not by default try to resolve data symbols until the first
- call is made to a particular object we can create the situation where no
- attempt to resolve the offending external data symbol is made until a
- call is made to the object in which it is referenced.
-
- Here's an example of how that works: Let us suppose that
- has_extern_data.o is an object with an undefined external in it which
- resides in the archive libxyz.a Here is how to isolate that external
- data reference:
-
- First make has_extern_data.o into a shared object all its own.
-
- % ar x libxyz.a has_extern_data.o
- % ld -shared has_extern_data.o -o has_extern_data.so
-
- Now, make libxyz.so, excluding has_extern_data.o from being included
- directly, but instead putting it in the liblist of libxyz.so
-
- Page 17 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- % ld -shared -all -exclude has_extern_data.o libxyz.a has_extern_data.so -o libxyz.so
-
- 28) What should I do about a GOT overflow?
- By default, addresses are loaded out of the Global Offset Table (GOT)
- using a 16 bit offset from a context pointer. This means that the size
- of the GOT is limited (by default) to 64K bytes, or about 16 K symbols.
- When there are too many symbols referenced by a DSO (or a.out) the linker
- issues the messag "GOT overflows" and will specify an object file which
- references the symbol which is "out of reach".
-
- SGI recommends that when developers encounter this problem, they attempt
- to split the DSO or a.out in question into several smaller DSO's, each of
- which can conform to the GOT size limit. Maximum performance can be
- achieved this way.
-
- However, as an alternative, developers may wish to use the -xgot
- compile-time flag to tell the compiler to issue a different (and slower)
- code sequence uses a 32-bit offset. This will allow the GOT to contain
- up to 1G entries. However, it is critical that every object linked into
- a final DSO or a.out be compiled with -xgot turned on, otherwise code may
- have been generated which will not work with an extended GOT. However,
- files compiled with -xgot may be linked into a DSO or a.out which has a
- GOT that does not exceed the 16K limit and will work correctly, if
- somewhat slower. The GOT size of any shared objects linked is
- irrelevant.
-
- The directory /usr/lib/xgot contains the extended-GOT versions of those
- objects which SGI has built both normally and -xgot. If a system or third
- party archive contains small GOT objects which are needed in an extended
- GOT link, a developer can take the following steps: 1) Look in
- /usr/lib/xgot to see if an extended GOT version exists. 2) Turn the
- archive into its own shared object, thus isolating it from the extended
- GOT binary. 3) contact the archive provider. In a few cases (crt1.o,
- crtn.o, c++init.o, and fixade.o), where the performance issues were
- minimal, the default objects in /usr/lib are in fact built large GOT.
-
- 29) How are multiple versions of DSO's supported?
- IRIX 5.0.1 (Compilers v3.16) and later supports the ability to tag shared
- objects and executables with a version number. This is intended to
- support interface changes. Details are below; items marked (SGI ONLY) do
- not apply to MSIG ABI binaries, but only to binaries generated on IRIX
- without the -abi flag turned on.
-
- Versioning of Shared Objects.
-
- QUICK OVERVIEW
-
- In order for a shared object to be versioned in the future
- the following needs to be done:
-
- * Version strings consist of 3 parts and a dot: The string "sgi",
- a decimal number (the major number), a dot, and a decimal number
-
- Page 18 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- (the minor number).
-
- * Add the command -set_version sgi1.0 to the command to build
- the shared object (cc -shared, ld -shared, etc.).
-
- * (Future) Whenever you make a COMPATIBLE change update the minor version
- number (the one after the dot), and add the latest version string
- to colon-separated list of version strings, e.g., -set_version
- sgi1.0:sgi1.1:sgi1.3
-
- * (Future) Whenever you make an INCOMPATIBLE change, update the
- major version number. Pass this as the version list, e.g.,
- -set_version sgi2.0. Change the filename of the OLD shared object
- by adding a dot followed by the previous major number to the filename
- of the shared object. DO NOT CHANGE the soname of the object.
- No change to the file contents are necessary or desirable. Simply
- rename the file.
-
- HOW IT ALL WORKS
-
- * Versioning will only be available for NON-ABI executables.
- The current ABI does not require objects to have versioning, nor
- does it require systems to pay attention to versioning. It does
- allow objects to contain version strings, but does not require
- systems to do anything with this information.
-
- * NON-ABI compliant executables will have a SGI_ONLY bit turned
- on in the .dynamic section. This flag will be understood and
- reported by elfdump. Only executables with this flag on will
- get the versioning treatment described below. This flag will
- be on by default.
-
- * When an executable is linked against a shared object, the last
- entry of the shared object's version string is recorded in the
- executable as part of the liblist. This can be examined by
- elfdump -Dl.
-
- * When an executable is linked, the user may specify -require_minor or
- -ignore_minor for each shared object linked against. If
- -require_minor is specified, a bit will be set in the flags field of
- the liblist entry for the shared object in question. The default
- is -ignore_minor.
-
- * When an executable (ABI or SGI_ONLY) is run rld will look
- for the proper filename in its usual search routine.
-
- * (SGI_ONLY) If a file with the correct name is found the
- version string in the liblist is compared to the list
- of version strings in the shared object. If the REQUIRE_MINOR bit
- is set in the liblist entry, and there is an exact match between the
- version string in the depender and one of the strings in the version
- list of the dependee, then that library is used. If the
-
- Page 19 Release 5.2
-
- DSO(5) Silicon Graphics DSO(5)
-
- REQUIRE_MINOR bit is clear, and if there is a match of major
- versions, then that library is used.
-
- * (SGI_ONLY) If no proper match is found, a new soname is built
- by taking the soname found in the executables liblist, and the
- major number found in the version string corresponding to that
- liblist entry, and putting them together as <soname>.<major>
- This is searched for in the same way as above. Version strings are
- matched in exactly the same way as described above.
-
- 30) Where can I find more documentation on DSO?
- Besides the other manpages mentioned below, System V Application Binary
- Interface and System V Application Binary Interface -- are both good
- sources of DSO implementation details.
-
- SEE ALSO
- rld(1), ld(1), elf(5), elfdump(1), dlopen(3), sgidladd(3)
-
- UPDATES
- This man page is periodically updated; the last update done on
- 1993/11/08 for IRIX 5.2.
-
- Page 20 Release 5.2
-